<?php 
class RightDAO {
	// debug-Logger
	static $debug;
	
	// Datenbank Objekt
	private $db;
	
	// Hier steht immer der aktuellste Fehler drin
	private $error = null;
	
	/**
	 * Der Konstruktor stattet die DAO mit einem DB Objekt aus
	 */
	function __construct() {
		if (!isset(self::$debug)) {
			self::$debug = DebugQuery::getInstance();
		}
		$this->db = DBFactory::getInstance();
	}
	
	/**
	 * Der Destruktor entfernt die Referen auf das DB Objekt
	 */
	function __destruct() {
		unset($this->db);
	}
	
	/**
	 * Diese Methode gibt ein array mit allen Right Entitäten zurück.
	 * 
	 * Jedes Recht wird hierbei durch ein Right Objekt representiert.
	 * 
	 * @return numerisches array mit Right Objekten, wenn erfolgreich, sonst null und Fehler in error
	 */
	public function get_all() {
		// Wenn vorher ein Fehler aufgetreten ist, schlucken
		$this->handle_previous_error();
		
		$ret = array();
		
		// debug
		if (DEBUG_ENABLED)
			self::$debug->append("Loading all entities of Right from Database...\n");
			
		// Query zum laden aller Right Objekte aus der DB
		$sql = 'SELECT
					ID,
					Name
				FROM
					Rights';
		
		// Query vorbereiten
		if (!$stmt = $this->db->prepare($sql)) {
			// Error in der DB Instanz
			$this->error = ERR_DATABASE_RETURNS_ERROR. $this->db->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in database object: %s\n", $this->error);
			
			return null;
		}
		
		// Query ausführen
		if (!$stmt->execute()) {
			// Error im Statement
			$this->error = ERR_STATEMENT_RETURNS_ERROR. $stmt->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in statment: %s\n", $this->error);
			
			return null;
		}
		
		// Ergebnis binden und auslesen
		$stmt->bind_result($id, $name);
		while($stmt->fetch()) {
			$ret[] = new Right($id, $name);
		}
		
		// Statement schließen
		$stmt->close();
		
		// debug
		if (DEBUG_ENABLED)
			self::$debug->append("Successfully loaded %d Right objects from database\n", count($ret));
		
		return $ret;
	} 
	
	/**
	 * Diese Methode liest die Entität von Right mit der id aus der Datenbank
	 * 
	 * @param integer $id id der Entität
	 * @return Right wenn vorhanden, sonst null
	 */
	public function getById($id) {
		// Wenn vorher ein Fehler aufgetreten ist, schlucken
		$this->handle_previous_error();
		
		$ret = null;
		
		// debug
		if (DEBUG_ENABLED)
			self::$debug->append("Loading Right with id '%d' from database...\n", $id);
		
		// Query zum laden der Right Entität mit der entsprechenden ID
		$sql = 'SELECT
					ID,
					Name
				FROM
					Rights
				WHERE
					ID = ?';
		
		// Query vorbereiten
		if (!$stmt = $this->db->prepare($sql)) {
			// Error in der DB Instanz
			$this->error = ERR_DATABASE_RETURNS_ERROR. $this->db->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in database object: %s\n", $this->error);
			
			return null;
		}
		
		// Platzhalter ersetzen
		$stmt->bind_param('i', $id);
		
		// Query ausführen
		if (!$stmt->execute()) {
			// Error im Statement
			$this->error = ERR_STATEMENT_RETURNS_ERROR. $stmt->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in statment: %s\n", $this->error);
			
			return null;
		}
		
		// Ergebnis an variablen binden
		$stmt->bind_result($id, $name);
		
		// Es dürfte höchstens eine Right Entität gefunden worden sein
		while($stmt->fetch()) {
			$ret = @new Right($id, $name); 
		}
		
		// Statement schließen
		$stmt->close();
		
		// debug
		if (DEBUG_ENABLED)
			self::$debug->append($ret ? "Loading Right entity with id '%d' was successfull.\n" : "No Right entity found with id '%d.\n", $id);
		
		return $ret;
	}
	
/**
	 * Diese Methode liest die Entität von Right mit dem namen aus der Datenbank
	 * 
	 * @param strin $name name der Entität
	 * @return Right wenn vorhanden, sonst null
	 */
	public function getByName($name) {
		// Wenn vorher ein Fehler aufgetreten ist, schlucken
		$this->handle_previous_error();
		
		$ret = null;
		
		// debug
		if (DEBUG_ENABLED)
			self::$debug->append("Loading Right with name '%s' from database...\n", $name);
		
		// Query zum laden der Right Entität mit dem entsprechenden Namen
		$sql = 'SELECT
					ID,
					Name
				FROM
					Rights
				WHERE
					Name = ?';
		
		// Query vorbereiten
		if (!$stmt = $this->db->prepare($sql)) {
			// Error in der DB Instanz
			$this->error = ERR_DATABASE_RETURNS_ERROR. $this->db->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in database object: %s\n", $this->error);
			
			return null;
		}
		
		// Platzhalter ersetzen
		$stmt->bind_param('s', $name);
		
		// Query ausführen
		if (!$stmt->execute()) {
			// Error im Statement
			$this->error = ERR_STATEMENT_RETURNS_ERROR. $stmt->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in statment: %s\n", $this->error);
			
			return null;
		}
		
		// Ergebnis an variablen binden
		$stmt->bind_result($id, $name);
		
		// Es dürfte höchstens eine Right Entität gefunden worden sein
		while($stmt->fetch()) {
			$ret = @new Right($id, $name); 
		}
		
		// Statement schließen
		$stmt->close();
		
		// debug
		if (DEBUG_ENABLED)
			self::$debug->append($ret ? "Loading Right entity with name '%s' was successfull.\n" : "No Right entity found with name '%s'.\n", $name);
		
		return $ret;
	}
	
	/**
	 * Diese Methode speichert ein Right Entität in die Datenbank
	 * 
	 * @param Right $right die Entität
	 * @return ID, falls erfolgreich, sonst null und Fehler in error
	 */
	public function save($right) {
		// Wenn vorher ein Fehler aufgetreten ist, schlucken
		$this->handle_previous_error();
		
		$ret = null;
		
		// debug
		if (DEBUG_ENABLED)
			self::$debug->append("Saving the Right entity '%s' to the database...", $right->get_name() );
		
		// Prüfen, ob es die Right Entität schon gibt
		if ($this->getByName($right->get_name())) {
			// Exsistiert bereits
			$this->error = ERR_RIGHT_ALREADY_EXSISTS. $right->get_name();
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Right with name '%s' already exsists.", $right->get_name());
				
			return null;
		}
			
		// Query zum Speichern einer Right Entität
		$sql = 'INSERT INTO
					Right(Name)
				VALUES
					(?)';
		
		// Statement vorbereiten
		if (!$stmt = $this->db->prepare($sql)) {
			// Error in der DB Instanz
			$this->error = ERR_DATABASE_RETURNS_ERROR. $this->db->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in database object: %s\n", $this->error);
			
			return null;
		}
		
		// Platzhalter ersetzen
		$stmt->bind_param('s', $right->get_name());
		
		// Query ausführen
		if (!$stmt->execute()) {
			// Error im Statement
			$this->error = ERR_STATEMENT_RETURNS_ERROR. $stmt->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in statment: %s\n", $this->error);
			
			return null;
		}
		
		// RightID auslesen
		$ret = $stmt->insert_id;
		
		// Gab es einen Fehler?
		if (!$ret) {
			// Error im Statement
			$this->error = ERR_STATEMENT_RETURNS_ERROR. $stmt->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in statment: %s\n", $this->error);
			
			return null;
		}
		
		// Statement schließen
		$stmt->close();
		
		// debug
		if (DEBUG_ENABLED)
			self::$debug->append("Right '%s' was saved successfully.\n", $right->get_name());
		
		return $ret;
	}
	
	/**
	 * Diese Methode updated die Right Entität
	 * 
	 * @param Right $right die Right Entität
	 * @return RightID wenn erfolgreich, sonst null und Fehler in error
	 */
	public function update($right) {
		// Wenn vorher ein Fehler aufgetreten ist, schlucken
		$this->handle_previous_error();
		
		$ret = null;
		
		// debug
		if (DEBUG_ENABLED)
			self::$debug->append("Updating Right '%s'...\n", $right->get_name());

		// Query zum aktualisieren der Right Entität
		$sql = 'UPDATE
					Right
				SET
					Name = ?
				WHERE
					ID = ?';
		
		// Statement vorbereiten
		if (!$stmt = $this->db->prepare($sql)) {
			// Error in der DB Instanz
			$this->error = ERR_DATABASE_RETURNS_ERROR. $this->db->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in database object: %s\n", $this->error);
			
			return null;
		}
		
		// Platzhalter ersetzen
		$stmt->bind_param('si', $right->get_name(), $right->get_id());
		
		// Query ausführen
		if (!$stmt->execute()) {
			// Error im Statement
			$this->error = ERR_STATEMENT_RETURNS_ERROR. $stmt->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in statment: %s\n", $this->error);
			
			return null;
		}
		
		// Statement schließen
		$stmt->close();
		
		// debug
		if (DEBUG_ENABLED)
			self::$debug->append("Right '%s' successfully updated.", $right->get_name());
		
		// An dieser Stelle ist alles super, deswegen id zurückgeben
		$ret = $right->get_id();
		
		return $ret;
	}
	
	/**
	 * Diese Methode löscht die Right Entität mit der übergebenen ID
	 * 
	 * @param integer $id
	 */
	public function deleteById($id) {
		// Wenn vorher ein Fehler aufgetreten ist, schlucken
		$this->handle_previous_error();
		
		$ret = null;
		
		// debug
		if (DEBUG_ENABLED)
			self::$debug->append("Deleting Right with id '%d'\n", $id);
			
		// Query zum löschen der Right Entität
		$sql = 'DELETE FROM
					Right
				WHERE
					ID = ?';
		
		// Statement vorbereiten
		if (!$stmt = $this->db->prepare($sql)) {
			// Error in der DB Instanz
			$this->error = ERR_DATABASE_RETURNS_ERROR. $this->db->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in database object: %s\n", $this->error);
			
			return null;
		}
		
		// Platzhalter ersetzen
		$stmt->bind_param('i', $id);
		
		// Query ausführen
		if (!$stmt->execute()) {
			// Error im Statement
			$this->error = ERR_STATEMENT_RETURNS_ERROR. $stmt->error;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Error in statment: %s\n", $this->error);
			
			return null;
		}
		
		// Statement schließen
		$stmt->close();
		
		// Probieren, ob es die Entität noch gibt
		if ($this->getById($id)) {
			// Löschen hat nicht geklappt
			$this->error = ERR_ENTITY_WAS_NOT_DELETED. $id;
			
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Right entity with id '%d' was not deleted.", $id);
				
			return null;
		}
		
		// debug
		if (DEBUG_ENABLED)
			self::$debug->append("Right entity successfully deleted.");
		
		return $ret;
	}
	
	/**
	 * Gibt den error aus und leert den internen error cache
	 */
	public function get_error() {
		$err = $this->error;
		$this->error = null;
		return $err;
	}
	
	/**
	 * Behandelt vorhergegangene nicht ausgelesene errors
	 */
	private function handle_previous_error() {
		// Falls vorher mal ein error aufgetreten ist, jedoch der
		// Fehler nicht ausgelesen wurde, wird dieser jetzt verworfen
		if ($pre_error = $this->get_error()) {
			// debug
			if (DEBUG_ENABLED)
				self::$debug->append("Previous error was not read: '%s'\n", $pre_error);
		}
	}
}
?>